home *** CD-ROM | disk | FTP | other *** search
- /*==============================================================================
-
- FICHERO: COLOR.C
-
- AUTOR: ANTONIO LADESA JURADO
-
- FECHA: 24/6/94
-
- DESCRIPCION:
-
- Fichero que contiene las estructuras, constantes, variables y funciones
- internas y externas para el tratamiento del color de las imágenes.
-
- ==============================================================================*/
-
-
- /*---- MODULOS USADOS --------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <alloc.h>
- #include <string.h>
-
- #include "global.h"
- #include "memoria.h"
- #include "video.h"
- #include "color.h"
- #include "error.h"
- #include "mapagris.pal"
-
- /*---- ESTRUCTURAS, CONSTANTES Y VARIABLES LOCALES AL MODULO -----------------*/
-
- /* pattern usado en el algoritmo de Bayer */
- static char BAYERpatron[8][8] =
- {
- 0,32, 8,40, 2,34,10,42,
- 48,16,56,24,50,18,58,26,
- 12,44, 4,36,14,46, 6,38,
- 60,28,52,20,62,30,54,22,
- 3,35,11,43, 1,33, 9,41,
- 51,19,59,27,49,17,57,25,
- 15,47, 7,39,13,45, 5,37,
- 63,31,55,23,61,29,53,21
- };
-
- /* buffers de entrada y salida para dither */
- char BufferEntrada[3][ANCHO_MAXIMO];
- char BufferSalida[ANCHO_MAXIMO];
- /* metodo dither usado */
- char metodo;
- /* niveles de gris equivalentes a blanco y negro */
- int blanco,negro;
- /* ultima línea procesada por el algoritmo de dither */
- int ultima;
- /* anchura y altura de la imagen, globales para el dither */
- int anchura,altura;
-
- /*---- DEFINICION DE LAS FUNCIONES INTERNAS ----------------------------------*/
-
- void DITHERpixel(int x,int y,int err);
- void ObtenerByN(int n,char *paleta);
- int LeerPixel(int x,int y);
- void PonerPixel(int x,int y,int n);
- void EscribirPixel(int x,int y,int n);
-
- /*---- CODIFICACION DE LAS FUNCIONES OFRECIDAS -------------------------------*/
-
-
- /*---- FUNCION: extern IMAGEN *PonerGris(IMAGEN *c) ----------------------------
-
- Descripción:
-
- Esta función transforma una imagen a color en tonos de gris.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
-
- Retorno:
-
- Puntero a la estructura de la imagen convertida.
- Si hay error, devuelve la misma imagen.
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern IMAGEN *PonerGris(IMAGEN *c)
- {
- /* puntero auxiliar a paleta */
- char *p;
- /* contador */
- int i;
- /* color obtenido */
- double color;
-
- switch(c->modo)
- {
- case VIDEOega:
- case VIDEOvga:
- /* si tiene paleta, se calculan los grises */
- if(c->haypaleta)
- {
- p = c->paleta;
- /* para todos los colores... */
- for(i=0;i<c->colores;++i,p+=3)
- {
- /* calcular nivel de gris */
- color = (0.30*(double)*p)+
- (0.59*(double)*(p+1))+
- (0.11*(double)*(p+2));
- if(color > 255.0)
- color = 255.0;
- /* poner gris los 3 componentes (RGB) */
- memset(p,mapagris[(char)color],3);
- }
- }
- else
- /* si no tiene paleta, crearla */
- {
- p = c->paleta;
- for(i=0;i<c->colores;++i,p+=3)
- memset(p,mapagris[i],3);
- c->haypaleta++;
- }
- break;
- };
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: extern IMAGEN *VideoInverso(IMAGEN *c) -------------------------
-
- Descripción:
-
- Esta función transforma una imagen en su negativo.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
-
- Retorno:
-
- Puntero a la estructura de la imagen convertida.
- Si hay error, devuelve la misma imagen.
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern IMAGEN *VideoInverso(IMAGEN *c)
- {
- /* contadores */
- int i,j;
- /* buffer para la línea */
- char buffer[ANCHO_MAXIMO];
-
- /* si es monocromática, cambiar blanco por negro */
- if(c->modo==VIDEOmono)
- for(i=0;i<c->alto;++i)
- {
- MEMleer(buffer,i,c);
- for(j=0;j<c->ancho;++j)
- *(buffer+j) = ~(*(buffer+j));
- MEMescribir(buffer,i,c);
- }
- else
- /* si es de color, invertir los colores de la paleta */
- {
- j=c->colores*3;
- for(i=0;i<j;i++)
- c->paleta[i] = 255 - c->paleta[i];
- }
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: extern IMAGEN *EscalarColores(IMAGEN *c,int colores) -----------
-
- Descripción:
-
- Esta función amplía o reduce el número de colores de una imagen.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
- int colores : nuevo número de colores de la imagen
- Retorno:
-
- Puntero a la estructura de la imagen convertida.
- Si hay error, devuelve la misma imagen.
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern IMAGEN *EscalarColores(IMAGEN *c,int colores)
- {
- /* buffer de línea */
- char bufferVGA[ANCHO_MAXIMO];
- /* contadores */
- int i,j;
- /* factor de reducción/ampliación de colores */
- double factor;
- /* nueva paleta de colores */
- char paleta[768];
-
- /* si no hay escalado, volver */
- if(c->colores == colores)
- return(c);
-
- /* calcular factor de escalado de colores */
- factor=(double)colores/(double)c->colores;
- memset(paleta,0,768);
- /* crear nueva paleta de colores */
- for(i=0;i<colores;++i)
- {
- paleta[i*3] = c->paleta[(i/factor)*3];
- paleta[i*3+1] = c->paleta[(i/factor)*3+1];
- paleta[i*3+2] = c->paleta[(i/factor)*3+2];
- }
- /* copiar nueva paleta */
- memcpy(c->paleta,paleta,768);
- /* ajustar índices de la imagen a la paleta */
- for(i=0;i<c->alto;++i)
- {
- MEMleer(bufferVGA,i,c);
- for(j=0;j<c->ancho;++j)
- bufferVGA[j] = (double)bufferVGA[j]*factor;
- MEMescribir(bufferVGA,i,c);
- }
- c->colores = colores;
- return(c);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: extern IMAGEN *BlancoYNegro(IMAGEN *c,char m) ------------------
-
- Descripción:
-
- Esta función transforma una imagen a color en blanco y negro.
- Para ello usa un método de dithering:
- Bayer, Floid-Steinberg, Stucki o Burkes.
-
- Parámetros:
-
- IMAGEN *c : puntero a estructura que alberga la imagen
- char m: método usado
-
- Retorno:
-
- Puntero a la estructura de la imagen convertida.
- Si hay error, devuelve la misma imagen.
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- extern IMAGEN *BlancoYNegro(IMAGEN *c,char m)
- {
- /* puntero a la nueva imagen */
- IMAGEN *byn = NULL;
- /* error de difusion */
- int err;
- /* coordenadas del pixel a tratar */
- int x,y;
- /* contadores de línea */
- int z,ln;
- /* color en proceso */
- int n;
-
- /* si no hay imagen, error */
- if(c == NULL)
- {
- ERRORponer(ERRnoImagen);
- return(c);
- }
-
- /* reservar memoria para la cabecera de trabajo */
- if((byn=MEMreservarCAB(byn))==NULL)
- {
- ERRORponer(ERRnoMemoria);
- return(c);
- }
-
- /* obtener niveles de blanco y negro */
- ObtenerByN(c->colores,c->paleta);
-
- /* cargar cabecera de trabajo */
- strcpy(byn->nombre,c->nombre);
- byn->ancho = c->ancho & 0xFFF7;
- byn->alto = c->alto;
- byn->formato = c->formato;
- byn->modo = VIDEOmono;
- byn->colores = 2;
- byn->haypaleta = 0;
- byn->bytes = DePixelsABytes(c->ancho);
- if(byn->bytes & 1) byn->bytes++;
- anchura = c->ancho;
- altura = c->alto;
- metodo = m;
-
- /* reservar memoria para la imagen */
- if(!MEMreservar(byn))
- {
- byn =MEMliberar(byn);
- return(c);
- }
-
- /* determinar líneas de trabajo, según el método usado */
- switch(metodo)
- {
- case BAYER:ln=1; break;
- case FLOYD:ln=2; break;
- case STUCKI:ln=3; break;
- case BURKES:ln=3; break;
- }
-
- /* proceso */
- for(y=0;y<altura;++y)
- {
- ultima=y;
-
- /* leer las líneas requeridas por el método en uso */
- for(z=0;z<ln;++z)
- {
- if((y+z)<c->alto)
- MEMleer(BufferEntrada[z],y+z,c);
- }
-
- /* limpiar buffer de salida */
- memset(BufferSalida,0,ANCHO_MAXIMO);
-
- /* para cada pixel x de la línea y... */
- for(x=0;x<anchura;++x)
- {
- /* si es dither Bayer, leer pixel y escribirlo según el patrón */
- if(metodo == BAYER)
- {
- n = LeerPixel(x,y);
- /* si lo supera, escribir blanco */
- if((n>>2) > BAYERpatron[x&7][y&7])
- EscribirPixel(x,y,1);
- else
- /* si no, escribir negro */
- EscribirPixel(x,y,0);
- continue;
- }
-
- /* si es otro método, leer pixel */
- if((n=LeerPixel(x,y))>((blanco+negro)/2))
- {
- /* Si supera el umbral, escribir blanco */
- EscribirPixel(x,y,1);
- /* establecer error de difusión, color menos nivel de blanco */
- err=n-blanco;
- }
- else
- {
- /* Si no supera el umbral, escribir negro */
- EscribirPixel(x,y,0);
- /* establecer error de difusión, color menos nivel de negro */
- err=n-negro;
- }
- /* aplicar el método de dithering */
- DITHERpixel(x,y,err);
- }
-
- /* si no es Bayer, escribir las líneas con los errores difundidos */
- for(z=1;z<ln;++z)
- {
- if((y+z)<c->alto)
- MEMescribir(BufferEntrada[z],y+z,c);
- }
-
- /* escribir la línea resultante */
- MEMescribir(BufferSalida,y,byn);
- }
-
- /* liberar imagen anterior y devolver la nueva */
- c = MEMliberar(c);
- c = NULL;
- return(byn);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
- /*---- CODIFICACION DE LAS FUNCIONES INTERNAS --------------------------------*/
-
-
- /*---- FUNCION: void ObtenerByN(int n,char *paleta) ----------------------------
-
- Descripción:
-
- Esta función determina los niveles para blanco y negro de una imagen
- según su paleta y número de colores
-
- Parámetros:
-
- int n: número de colores
- char *paleta: paleta de colores
-
- Retorno:
-
- Actualiza las variables globales blanco y negro
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void ObtenerByN(int n,char *paleta)
- {
- /* paleta auxiliar */
- char paletagris[256];
- /* gris obtenido */
- double f;
- /* contador */
- int i;
-
- /* niveles de blanco y negro */
- blanco = 0;
- negro = n-1;
-
- /* para todos los colores */
- for(i=0;i<n;++i)
- {
- /* calcular nivel de gris */
- f=(0.30*(double)*paleta++)+
- (0.59*(double)*paleta++)+
- (0.11*(double)*paleta++);
- if(f>255.0) f=255.0;
- /* calcular niveles de blanco y negro */
- paletagris[i]= mapagris[(char)f];
- if(paletagris[i]<negro) negro = paletagris[i];
- if(paletagris[i]>blanco) blanco = paletagris[i];
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void DITHERpixel(int x,int y,int err) --------------------------
-
- Descripción:
-
- Esta función aplica la difusión de error de un pixel a los pixels
- correspondientes según el método de dithering empleado
-
- Parámetros:
-
- int x: coordenada x del pixel
- int y: coordenada y del pixel
- int err: error de difusión
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void DITHERpixel(int x,int y,int err)
- {
- /* difundir errores a los pixels implicados, según el método usado */
- switch(metodo)
- {
- case FLOYD:
- PonerPixel(x+1,y,LeerPixel(x+1,y)+((7*err)/16));
- PonerPixel(x-1,y+1,LeerPixel(x-1,y+1)+((3*err)/16));
- PonerPixel(x,y+1,LeerPixel(x,y+1)+((5*err)/16));
- PonerPixel(x+1,y+1,LeerPixel(x+1,y+1)+(err/16));
- break;
- case STUCKI:
- PonerPixel(x+2,y,LeerPixel(x+2,y)+((8*err)/42));
- PonerPixel(x+1,y,LeerPixel(x+1,y)+((4*err)/42));
- PonerPixel(x-2,y+1,LeerPixel(x-2,y+1)+((2*err)/42));
- PonerPixel(x-1,y+1,LeerPixel(x-1,y+1)+((4*err)/42));
- PonerPixel(x,y+1,LeerPixel(x,y+1)+((8*err)/42));
- PonerPixel(x+1,y+1,LeerPixel(x+1,y+1)+((4*err)/42));
- PonerPixel(x+2,y+1,LeerPixel(x+2,y+1)+((2*err)/42));
- PonerPixel(x-2,y+2,LeerPixel(x-2,y+2)+((1*err)/42));
- PonerPixel(x-1,y+2,LeerPixel(x-1,y+2)+((2*err)/42));
- PonerPixel(x,y+2,LeerPixel(x,y+2)+((4*err)/42));
- PonerPixel(x+1,y+2,LeerPixel(x+1,y+2)+((2*err)/42));
- PonerPixel(x+2,y+2,LeerPixel(x+2,y+2)+((1*err)/42));
- break;
- case BURKES:
- PonerPixel(x+2,y ,LeerPixel(x+2,y )+((8*err)/32));
- PonerPixel(x+1,y ,LeerPixel(x+1,y )+((4*err)/32));
- PonerPixel(x-2,y+1,LeerPixel(x-2,y+1)+((2*err)/32));
- PonerPixel(x-1,y+1,LeerPixel(x-1,y+1)+((4*err)/32));
- PonerPixel(x ,y+1,LeerPixel(x ,y+1)+((8*err)/32));
- PonerPixel(x+1,y+1,LeerPixel(x+1,y+1)+((4*err)/32));
- PonerPixel(x+2,y+1,LeerPixel(x+2,y+1)+((2*err)/32));
- break;
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void LeerPixel(int x,int y) ------------------------------------
-
- Descripción:
-
- Esta función devuelve el valor del pixel x,y desde la línea correspondiente
- del buffer de entrada
-
- Parámetros:
-
- int x: coordenada x del pixel
- int y: coordenada y del pixel
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- int LeerPixel(int x,int y)
- {
- /* leer pixel desde la entrada */
- return(BufferEntrada[y-ultima][x]);
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void PonerPixel(int x,int y,int n) -----------------------------
-
- Descripción:
-
- Esta función pone nuevo color al pixel x,y en la línea correspondiente
- del buffer de entrada, transmite el error al pixel.
-
- Parámetros:
-
- int x: coordenada x del pixel
- int y: coordenada y del pixel
- int n: nivel de gris
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void PonerPixel(int x,int y,int n)
- {
- /* poner nuevo color a un pixel (transmitir error) en el buffer de entrada */
- if(x>=0 && x < anchura && y >= 0 && y < altura)
- {
- if(n<negro) n=negro;
- if(n>blanco) n=blanco;
- BufferEntrada[y-ultima][x]=n;
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/
-
-
- /*---- FUNCION: void EscribirPixel(int x,int y,int n) -----------------------------
-
- Descripción:
-
- Esta función pone el pixel x,y en el buffer de salida,
- desplazando los bits según la posición del pixel.
-
- Parámetros:
-
- int x: coordenada x del pixel
- int y: coordenada y del pixel
- int n: color (blanco o negro)
-
- ---- CODIGO: -----------------------------------------------------------------*/
-
- void EscribirPixel(int x,int y,int n)
- {
- /* si existe el pixel...*/
- if(x>=0 && x < anchura && y >= 0 && y < altura)
- {
- /* poner blanco o negro, desplazando los bits según la posición */
- if(n)
- BufferSalida[x>>3] |= (0x80>>(x & 0x0007));
- else
- BufferSalida[x>>3] &= ~(0x80>>(x & 0x0007));
- }
- }
-
- /*---- FIN FUNCION -----------------------------------------------------------*/